﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Reflection;

namespace Ganaye.EmbeddedDb
{
    public abstract class Record 
    {
        internal protected Table mTable; // need to be protected for proxy
        internal protected FieldState[] mFieldStates;
        internal UInt32 mRecordNo;
        internal short mPendingUpdateCount;
        //private Byte[] mReadBuffer;
#if ASSERTS
        string mConstructorStack;
#endif

        public Record()
        {
#if ASSERTS
            mConstructorStack = Environment.StackTrace;
#endif
        }

        public object this[string columnName]
        {
            get
            {
                TableColumn column = mTable.GetColumnByName(columnName,/*return null*/ false);
                return column.SlowGetValue(this);
            }
            set
            {
                TableColumn column=mTable.GetColumnByName(columnName,/*return null*/ false);
                column.SlowSetValue(this, value);
            }
        }

        public object this[int columnIndex]
        {
            get
            {
                TableColumn column = mTable.GetColumnByNumber(columnIndex);
                return column.SlowGetValue(this);
            }
            set
            {
                TableColumn column = mTable.GetColumnByNumber(columnIndex);
                column.SlowSetValue(this, value);
            }
        }

        //public object this[RecordColumn recordColumn]
        //{
        //    get
        //    {
        //        TableColumn column = recordColumn.GetTableColumn(mTable,/*return null*/ false);
        //        return InternalGetValue(column);
        //    }
        //    set
        //    {
        //        TableColumn column = recordColumn.GetTableColumn(mTable,/*return null*/ false);
        //        SlowSetValue(column, newValue);
        //    }
        //}
        
        protected TableColumn GetColumn1(int i)
        {
            return mTable.mColumns[i];
        }

        protected TableColumn GetColumn2(int i)
        {
            return mTable.mColumns[i];
        }

        protected TableColumn GetColumn3(int i)
        {
            return mTable.mColumns[i];
        }

        protected string Get_DBASE3_CHARACTER(ColumnDefinition col)
        {

            return null;
        }
        protected string Get_DBASE3_DBASE3_NUMBER(ColumnDefinition col)
        {
            return null;
        }
        protected bool? Get_DBASE3_LOGICAL(ColumnDefinition col)
        {
            return null;
        }
        protected DateTime? Get_DBASE3_DATE(ColumnDefinition col)
        {
            return null;
        }
        protected string Get_DBASE3_MEMO(ColumnDefinition col)
        {
            return null;
        }
        protected double? Get_DBASE4_FLOAT(ColumnDefinition col)
        {
            return null;
        }
        protected string Get_DBASE5_BINARY(ColumnDefinition col)
        {
            return null;
        }
        protected string Get_DBASE5_GENERAL(ColumnDefinition col)
        {
            return null;
        }
        protected string Get_FOXPRO_PICTURE(ColumnDefinition col)
        {
            return null;
        }
        protected decimal? Get_FOXPRO_CURRENCY(ColumnDefinition col)
        {
            return null;
        }
        protected DateTime? Get_FOXPRO_DATETIME(ColumnDefinition col)
        {
            return null;
        }
        protected Int32? Get_FOXPRO_INTEGER(ColumnDefinition col)
        {
            return null;
        }
        protected string Get_FOXPRO_VARIFIELD(ColumnDefinition col)
        {
            return null;
        }
        protected string Get_FOXPRO_VARCHAR(ColumnDefinition col)
        {
            return null;
        }
        protected DateTime? Get_FOXPRO_TIMESTAMP(ColumnDefinition col)
        {
            return null;
        }
        protected double? Get_FOXPRO_DOUBLE(ColumnDefinition col)
        {
            return null;
        }
        protected Int32? Get_FOXPRO_AUTOINC(ColumnDefinition col)
        {
            return null;
        }


        public Table Table
        {
            get
            {
                return mTable;
            }
        }

        public UInt32 RecordNo
        {
            get { return mRecordNo; }
        }
        #region IDisposable Members


#if ASSERTS
        ~Record()
        {
            System.Diagnostics.Debug.Assert(this.mPendingUpdateCount==0, string.Format("Record {0} #{1} is being finalized with {2} updates pending.\n{3}", 
                this.GetType().Name, 
                mRecordNo,
                mPendingUpdateCount,
                mConstructorStack));
        }
#endif

        #endregion

        public void Save()
        {
        }

        public void Flush()
        {
        }

        public bool IsModified
        {
            get { return false; }
        }

        //'good thing on bu/eu is that it can be nested

        public PendingRecordUpdate BeginUpdates()
        {
            mPendingUpdateCount++;
            return new PendingRecordUpdate(this);
        }

        

        internal byte[] InternalGetWriteBytes()
        {
            int columnCount = mTable.mColumns.Count;
            for (int i = 0; i < columnCount; i++)
            {
                if (mFieldStates[i] == FieldState.Modified)
                {
                    //var Column = GetColumn1[i];
                    var column = mTable.mColumns[i];
                    column.mQuickSaveToBytes(this);
                }
            }
            return GetReadBuffer();
        }

        public abstract Byte[] GetReadBuffer();
    }
}
